#include <string>

using namespace std;

class HasPtr {
    friend void swap(HasPtr&, HasPtr&);
public:
    HasPtr(const std::string &s = std::string()) :
        ps(new std::string(s)), i(0) { }
    HasPtr(const HasPtr&);
    HasPtr& operator =(const HasPtr&);
    ~HasPtr() { delete ps; }
private:
    std::string *ps;
    int i;
};

// 拷贝构造函数
HasPtr::HasPtr(const HasPtr &hp)
{
    ps = new std::string(*hp.ps);   // 拷贝 ps 指向的对象，而不是拷贝指针本身
//    ps = hp.ps;                     // 拷贝的是指针本身
    i = hp.i;
}

// 拷贝赋值构造函数
HasPtr&
HasPtr::operator =(const HasPtr &rhs)
{
    auto newps = new string(*rhs.ps);   // 拷贝指针指向的对象
    delete ps;  // 销毁原 string
    ps = newps; // 指向新 string
    i = rhs.i;  // 使用内置的 int 赋值
    return *this;   // 返回一个此对象的引用
}

inline void swap(HasPtr &lhs, HasPtr &rhs)
{
    cout << "交换" << *lhs.ps << "和" << *rhs.ps << endl;
    swap(lhs.ps, rhs.ps);   // 交换指针,而不是 string 数据
    swap(lhs.i, rhs.i); // 交换 int 成员
}

void test_13_30()
{
    HasPtr h("hi mom!");
    HasPtr h2(h);
    HasPtr h3 = h;
    h2 = "hi dad!";
    h3 = "hi son!";
    swap(h2, h3);
    cout << "h: " << *h << endl;
    cout << "h2: " << *h2 << endl;
    cout << "h3: " << *h3 << endl;
}
